Repository navigation
refactor(work-items): read the execution handoff modes from the vocabulary owner - #8184
Conversation
f74581a to
8ac2638
Compare
…ulary owner execution_preparation.ts restated the two accepted modes under the name HANDOFF_MODES, which is the vocabulary owner's three-value historical list. Bind the validator to EXECUTION_HANDOFF_MODES, the list the TypeScript migration RFC names for new execution and configuration targets, and pin the two lists apart so widening the input vocabulary fails a test. Signed-off-by: Jiaqiiii523 <293262669+Jiaqiiii523@users.noreply.github.com>
8ac2638 to
60c62f5
Compare
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.
动机 / Motivation
维护执行准入与租约代码的开发者,需要区分历史状态解码和新执行所允许的模式。 此前执行准备模块自行保存 soft_claim/hard_lease 双值表,却把它叫作 HANDOFF_MODES;共享 owner 中同名表还包含 legacy。以后改规则需要同步副本,按名字误换引用还可能扩大准入。现在直接读取共享的执行子集,消除这个同步点。 执行准备已复用既有 EXECUTION_HANDOFF_MODES;原来的正常准备、冲突拒绝和 legacy 拒绝结果保持。 范围仅是这个执行准备投影,不新增模式、不修改 claim/lease 权限或历史解码,也不声称完成整个迁移路线图或取得性能收益。
这是一个独立可验收的维护切片。当前运行结果原本就应正确;价值是移除第二个规则来源,降低以后修改词汇时误用历史列表的风险。维持原状会保留该同步点,单纯改名也不能消除副本。
改动思路 / Approach
这是对既有无依赖词汇 owner 的直接复用;保留历史三值表与执行双值表的语义分工,比新增 wrapper 或按同名导出替换更合适。 当前 PR 只删除执行准备模块的本地副本并增加一个拒绝范围回归,不改变状态源、执行副作用、交互或安装默认。 原子 claim 仍负责重新核对归属、写入范围和工作树,执行准备只读规范事实并返回下一步,不会因导入一个列表就获取租约或额外权限。没有必要再加模式转换、兼容 wrapper 或新的开关。
| 列表 | 保留的用途 | 值 |
|---|---|---|
| HANDOFF_MODES | 历史状态和回执解码 | legacy、soft_claim、hard_lease |
| EXECUTION_HANDOFF_MODES | 新配置和执行目标 | soft_claim、hard_lease |
具体改动 / Changes
审查绑定 60c62f5,实际 merge-base 为 d0985c3。完整范围为两个文件:生产代码 +2/-2,测试 +22/-0;没有新增模块、状态、CLI、模式或协议版本。完整 diff、变更模块与测试均已阅读,也沿运行时 handler 和 Python quota caller 核对了真实调用点。
关键代码讲解
projectExecutionPreparation的模式校验改用现成的执行子集;后续无权威、任务不开放、外人持有、软 claim、硬 lease 和恢复分支保持原样。EXECUTION_HANDOFF_MODES是既有无依赖 owner。它与上面的历史列表用途不同,所以这次没有按名字直接换成更宽的 HANDOFF_MODES。project_selected_todo_execution_preparation仍从规范状态中筛选准确 Todo 和租约,再调用同一个 typed projector;它与普通 claim 才是实际准入链路,测试导入成功不能替代这条链路。
规格依据为 docs/architecture/rfcs/typescript-control-plane-migration-v0.md,固定在 d0985c35aa3d05fd5de964e719aaf69f45d72535(接受的原文)。Current delivery frontier (post-merge, 2026-10-16) 条款在本头为 implemented:新执行使用共享执行子集,历史 legacy 词汇保持,实际 legacy 执行输入仍被拒绝。这里没有把更广泛的迁移、默认采用或所有存储资格当成本切片的新前置条件。
新增回归直接检查两种正常模式与 legacy 拒绝,针对的是“误导入历史列表会扩大合法输入”这个独立语义。它服务实际生产校验,未把源码拼写或行数当成行为断言。相邻的 lease-status 词汇没有被顺便重构。
对主干的风险 / Risks
未发现阻塞问题。最强反例是历史列表仍含 legacy,却被误当成新执行列表;当前真实请求对此仍抛 typed error。另以 25 组相同事实覆盖软/硬模式、租约缺失/释放/过期、己方/外人持有、任务完成、无权威、多租约及非法 JSON 类型,两个版本的完整返回与错误 JSON 逐字一致,没有删掉字段、命令或 prose 来做归一化。
| 独立执行的检查 | 基线 | 当前头 |
|---|---|---|
| 完整 TypeScript lane | PASS:6147 passed,77 skipped,0 failed | PASS:6148 passed,77 skipped,0 failed |
| 真实 File/SQLite quota、claim 和恢复模块 | PASS:31 passed | PASS:31 passed |
| 25 组完整投影/错误对照 | 与候选逐字相同 | 与基线逐字相同 |
| TS typecheck、默认 mypy 17 roots、仓库 Ruff、semantic vocabulary smoke | — | PASS |
| 准确范围 CQR | — | PASS,verify valid |
两边在安装相同开发依赖后使用 Node 24.21.0 和同一完整 TS 命令;runner 均设 LOOPX_USAGE_PING=0。77 项 skipped 保持为跳过,没有称作通过。作者曾报告的两项 TS 失败属于其历史观测;本机本次基线和候选均无失败,原因差异未归因,不能说是本 PR 修好了那两个检查。当前改变的校验、真实调用与恢复有独立通过证据。没有查询或等待远端 CI,也未另外资格化安装态、真实 PostgreSQL 或模型成本。
语义与 CI 对齐
本提案 reuse_existing,没有创建词汇或扩大闭集。完整语义扫描通过;更关键的是执行集合仍为双值、历史三值集合未动,实际 legacy 拒绝和所有比较返回保持。claim 的准备义务、归属拒绝、原捕获恢复和停止条件没有新措辞或默认变化。
我的整体评价 / Verdict
对这个明确维护边界,交付判断为 goal_achieved。long_horizon 与 user_experience 均为 preserved:真实调用和恢复保持,用户没有新增准备、导航或确认轮次;维护改善限定为少一个重复规则来源,没有把测试数或共享导入换算成长期收益。更大迁移计划和实际效果/成本结论不由本评审关闭。
视觉检查不适用。两个变更文件没有渲染页面改动;已检查的 CLI/Host 调用方也没有新增呈现行为。没有验证打包 UI 或安装态 rollout;这不属于本次源码词汇合并的验收。当前源码范围无需再增加 wrapper、配置或后续任务。合并所需的当前权限、分支状态和保护仍由各自 owner 判定,本次批准不执行合并或安装。
English verdict: APPROVE for 60c62f5f593fcc75bff23a2f5a4e1f4055531bd2; the shared execution vocabulary preserves the current admission and recovery contract.
Goal And Delivered Outcome
docs/architecture/rfcs/typescript-control-plane-migration-v0.md:343, which states that new execution and configuration targets shareEXECUTION_HANDOFF_MODES(soft_claim/hard_lease), with the historicalHandoffModekept for decoding.loopx/control_plane/work_items/execution_preparation.ts:16restated those two modes locally under the nameHANDOFF_MODES— the exact name of the owner's three-value historical list atloopx/control_plane/coordination/handoff_mode_vocabulary.ts:2. Every other consumer of this vocabulary already imports it (local_authority_defaults.ts:6,handoff_mode_policy.ts:6,handoff_mode_migration.ts:14,work_items/task_lease_acquire.ts:1,work_items/task_lease_acquire_decision.ts:1,work_items/task_lease_lifecycle_decision.ts:1,quota/settlement_plan.ts:13, and the dashboard'sapps/presentation/dashboard/src/data/chat.ts:3), so this file was the one surface holding its own copy.integrationandstaticrows.main.Author Declaration
Implemented against
docs/architecture/rfcs/typescript-control-plane-migration-v0.md(and its Chinese pair, unchanged) at repositorymain62e234c939996ad42f2b1168451cc9a656dce11d; the owner module's own comments, which labelHANDOFF_MODESas "Shared wire vocabulary" andEXECUTION_HANDOFF_MODESas "New configuration targets".EXECUTION_HANDOFF_MODESloopx/control_plane/work_items/execution_preparation.ts:1,58node --experimental-strip-types --test tests/control_plane_ts/execution_preparation.test.tsHandoffModestays decodable but is not a new targettests/control_plane_ts/execution_preparation.test.ts(new case)const HANDOFF_MODES = [...] as constHANDOFF_MODESlist: it also containslegacy, so that "obvious" fold would silently widen the acceptedhandoff_modeinput on this surface — the new case is written specifically to fail if anyone does that. I leftLEASE_STATUSESalone; it has one definition, and folding it would be a different decision. NoPythontwin is claimed or moved here — the cross-runtime pair is governed by the migration RFC.Why this is a fold and not a rename
The local list and the owner's execution list are the same two values, so the change is behaviour-preserving on every accepted input. The name, however, was not the same thing:
HANDOFF_MODESin the owner carries the retiredlegacymode for stored-state decoding. Binding the validator to the value-matching export instead of the name-matching one keeps the accepted set at two while removing the duplicated list, and the pinned difference is what stops a future "cleanup" from importing the wider list.Scope And Continuation
tests/architecture/test_content_digest_single_owner.pydoes for Python, that is a separate decision; this PR does not pre-empt it.Validation
60c62f5f593fcc75bff23a2f5a4e1f4055531bd2integrationpassednode --no-warnings --experimental-sqlite --experimental-strip-types --test --test-concurrency=4 tests/control_plane_ts/*.test.ts) run twice on this host: identical footing ond0985c35aa3d05fd5de964e719aaf69f45d72535, with the same installed dev dependencies visible to both trees: clean base checkout → 6224 tests, 6145 pass, 2 fail; this head → 6225 tests, 6146 pass, 2 fail. The two failing test names are identical between the runs (persistent machine routes retain notice-before-default-on without an enable flag,temporary roots, filesystem aliases and path-component boundaries are local eligibility facts). Net regressions 0, and the +1 test is the new case. Earlier runs of this lane withoutnpm ciproduced 17 file-level failures in both trees; the dependency state, not the code, was the difference, so the row is restated on the equal-footing pair.real_entrypointpassednode --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/execution_preparation.test.ts→ 8 pass, 0 fail (7 before the change).regression_paritypassedEXECUTION_HANDOFF_MODESwith the owner's same-named three-valueHANDOFF_MODESin the changed source makes exactly the new case fail (7 pass / 1 fail); the file was restored and compared byte-identical afterwards.staticpassednpm ci --ignore-scriptsthentsc --project tsconfig.control-plane.json --noEmit→ no output, exit 0.unitnot_runFrontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
handoff_modeinput set on this surface stays exactlysoft_claim/hard_lease, which is the registeredhandoff_modevocabulary's execution subset inloopx/semantics/vocabulary_v0.json.Boundary Checklist
none.Signed-off-bytrailer.